﻿
using System.Collections.Generic;
using System.Linq;
using Adalbertus.BudgetPlanner.Domain;
using Adalbertus.BudgetPlanner.Domain.Repositories;

namespace Adalbertus.BudgetPlanner.Services
{
    public class ExternalSourceService : BaseService<ExternalSource>, IExternalSourceService
    {
        public ExternalSourceService(IRepositoryFactory repositoryFactory, IUnitOfWorkProvider unitOfWorkProvider) : base(repositoryFactory, unitOfWorkProvider)
        {
        }

        public override void Remove(ExternalSource externalSource)
        {
            using (IUnitOfWork unitOfWork = UnitOfWorkProvider.OpenUnitOfWork())
            {
                IRepository<ExternalSource> repository = RepositoryFactory.CreateRepository<ExternalSource>(unitOfWork);
                repository.Remove(externalSource);

                ICashFlowTypeRepository cashFlowTypeRepository = RepositoryFactory.CreateCashFlowTypeRepository(unitOfWork);
                CashFlowType cashFlowType = cashFlowTypeRepository.GetByExternalSource(externalSource);
                if (cashFlowType != null)
                {
                    cashFlowTypeRepository.Remove(cashFlowType);
                }
                
                unitOfWork.Commit();
            }
        }

        public ExternalSource AddEmptySavings()
        {
            return AddEmptyExternalSource(ExternalSourceType.Savings);
        }

        public ExternalSource AddEmptyIncome()
        {
            return AddEmptyExternalSource(ExternalSourceType.Incomes);
        }

        public void Save(ExternalSource externalSource, IEnumerable<ExternalSourceItem> items)
        {
            using (IUnitOfWork unitOfWork = UnitOfWorkProvider.OpenUnitOfWork())
            {
                externalSource.Items = items.ToList();
                IExternalSourceRepository repository = RepositoryFactory.CreateExternalSourceRepository(unitOfWork);
                repository.Save(externalSource);
                if (externalSource.SourceType == ExternalSourceType.Savings)
                {
                    ICashFlowTypeRepository cashFlowTypeRepository =
                        RepositoryFactory.CreateCashFlowTypeRepository(unitOfWork);
                    CashFlowType cashFlowType = cashFlowTypeRepository.GetByExternalSource(externalSource);
                    if (cashFlowType != null)
                    {
                        cashFlowType.Description = externalSource.Name;
                        cashFlowTypeRepository.Save(cashFlowType);
                    }
                }
                unitOfWork.Commit();
            }
        }

        #region Helper methods
        private ExternalSource AddEmptyExternalSource(ExternalSourceType sourceType)
        {
            using (IUnitOfWork unitOfWork = UnitOfWorkProvider.OpenUnitOfWork())
            {
                IExternalSourceRepository repository = RepositoryFactory.CreateExternalSourceRepository(unitOfWork);
                ExternalSource externalSource = new ExternalSource
                {
                    Name = "Brak nazwy...",
                    SourceType = sourceType
                };
                repository.Save(externalSource);
                externalSource.Name = string.Format("Domyślna nazwa {0}", externalSource.Id);
                repository.Save(externalSource);
                if (sourceType == ExternalSourceType.Savings)
                {
                    AddCashFlowTypeForExternalSource(unitOfWork, externalSource);
                }
                unitOfWork.Commit();
                return externalSource;
            }
        }

        private void AddCashFlowTypeForExternalSource(IUnitOfWork unitOfWork, ExternalSource externalSource)
        {
            IRepository<CashFlowType> cashFlowRepository = RepositoryFactory.CreateRepository<CashFlowType>(unitOfWork);
            CashFlowType cashFlowType = new CashFlowType
            {
                ExternalSource = externalSource
            };
            cashFlowRepository.Save(cashFlowType);
        }
        #endregion
    }
}
